package org.funny.machine32.base;

public enum OperationEnum {
    //算术运算
    ADD("add",      /**/ "000000ssssstttttfffff00000100000", false, "[add $t1,$t2,$t3]       Addition with overflow : set $t1 to ($t2 plus $t3)"),
    ADDI("addi",    /**/ "001000sssssffffftttttttttttttttt", false, "[addi $t1,$t2,-100]     Addition immediate with overflow : set $t1 to ($t2 plus signed 16-bit immediate)"),
    ADDIU("addiu",  /**/ "001001sssssffffftttttttttttttttt", false, "[addiu $t1,$t2,-100]    Addition immediate unsigned without overflow : set $t1 to ($t2 plus signed 16-bit immediate), no overflow"),
    ADDU("addu",    /**/ "000000ssssstttttfffff00000100001", false, "[addu $t1,$t2,$t3]      Addition unsigned without overflow : set $t1 to ($t2 plus $t3), no overflow"),
    CLO("clo",      /**/ "011100sssss00000fffff00000100001", false, "[clo $t1,$t2]           Count number of leading ones : Set $t1 to the count of leading one bits in $t2 starting at most significant bit position"),
    CLZ("clz",      /**/ "011100sssss00000fffff00000100000", false, "[clz $t1,$t2]           Count number of leading zeroes : Set $t1 to the count of leading zero bits in $t2 starting at most significant bit position"),
    LUI("lui",      /**/ "00111100000fffffssssssssssssssss", false, "[lui $t1,100]           Load upper immediate : Set high-order 16 bits of $t1 to 16-bit immediate and low-order 16 bits to 0"),
    SUB("sub",      /**/ "000000ssssstttttfffff00000100010", false, "[sub $t1,$t2,$t3]       Subtraction with overflow : set $t1 to ($t2 minus $t3)"),
    SUBU("subu",    /**/ "000000ssssstttttfffff00000100011", false, "[subu $t1,$t2,$t3]      Subtraction unsigned without overflow : set $t1 to ($t2 minus $t3), no overflow"),
    //移位运算
    SLL("sll",      /**/ "00000000000sssssfffffttttt000000", false, "[sll $t1,$t2,10]        Shift left logical : Set $t1 to result of shifting $t2 left by number of bits specified by immediate"),
    SLLV("sllv",    /**/ "000000tttttsssssfffff00000000100", false, "[sllv $t1,$t2,$t3]      Shift left logical variable : Set $t1 to result of shifting $t2 left by number of bits specified by value in low-order 5 bits of $t3"),
    SRA("sra",      /**/ "00000000000sssssfffffttttt000011", false, "[sra $t1,$t2,10]        Shift right arithmetic : Set $t1 to result of sign-extended shifting $t2 right by number of bits specified by immediate"),
    SRAV("srav",    /**/ "000000tttttsssssfffff00000000111", false, "[srav $t1,$t2,$t3]      Shift right arithmetic variable : Set $t1 to result of sign-extended shifting $t2 right by number of bits specified by value in low-order 5 bits of $t3"),
    SRL("srl",      /**/ "00000000000sssssfffffttttt000010", false, "[srl $t1,$t2,10]        Shift right logical : Set $t1 to result of shifting $t2 right by number of bits specified by immediate"),
    SRLV("srlv",    /**/ "000000tttttsssssfffff00000000110", false, "[srlv $t1,$t2,$t3]      Shift right logical variable : Set $t1 to result of shifting $t2 right by number of bits specified by value in low-order 5 bits of $t3"),
    //逻辑运算
    AND("and",      /**/ "000000ssssstttttfffff00000100100", false, "[and $t1,$t2,$t3]       Bitwise AND : Set $t1 to bitwise AND of $t2 and $t3"),
    ANDI("andi",    /**/ "001100sssssffffftttttttttttttttt", false, "[andi $t1,$t2,100]      Bitwise AND immediate : Set $t1 to bitwise AND of $t2 and zero-extended 16-bit immediate"),
    NOP("nop",      /**/ "00000000000000000000000000000000", false, "[nop]                   Null operation : machine32 code is all zeroes"),
    NOR("nor",      /**/ "000000ssssstttttfffff00000100111", false, "[nor $t1,$t2,$t3]       Bitwise NOR : Set $t1 to bitwise NOR of $t2 and $t3"),
    OR("or",        /**/ "000000ssssstttttfffff00000100101", false, "[or $t1,$t2,$t3]        Bitwise OR : Set $t1 to bitwise OR of $t2 and $t3"),
    ORI("ori",      /**/ "001101sssssffffftttttttttttttttt", false, "[ori $t1,$t2,100]       Bitwise OR immediate : Set $t1 to bitwise OR of $t2 and zero-extended 16-bit immediate"),
    XOR("xor",      /**/ "000000ssssstttttfffff00000100110", false, "[xor $t1,$t2,$t3]       Bitwise XOR (exclusive OR) : Set $t1 to bitwise XOR of $t2 and $t3"),
    XORI("xori",    /**/ "001110sssssffffftttttttttttttttt", false, "[xori $t1,$t2,100]      Bitwise XOR immediate : Set $t1 to bitwise XOR of $t2 and zero-extended 16-bit immediate"),
    //条件测试或转移
    MOVN("movn",    /**/ "000000ssssstttttfffff00000001011", false, "[movn $t1,$t2,$t3]      Move conditional not zero : Set $t1 to $t2 if $t3 is not zero"),
    MOVZ("movz",    /**/ "000000ssssstttttfffff00000001010", false, "[movz $t1,$t2,$t3]      Move conditional zero : Set $t1 to $t2 if $t3 is zero"),
    SLT("slt",      /**/ "000000ssssstttttfffff00000101010", false, "[slt $t1,$t2,$t3]       Set less than : If $t2 is less than $t3, then set $t1 to 1 else set $t1 to 0"),
    SLTI("slti",    /**/ "001010sssssffffftttttttttttttttt", false, "[slti $t1,$t2,-100]     Set less than immediate : If $t2 is less than sign-extended 16-bit immediate, then set $t1 to 1 else set $t1 to 0"),
    SLTIU("sltiu",  /**/ "001011sssssffffftttttttttttttttt", false, "[sltiu $t1,$t2,-100]    Set less than immediate unsigned : If $t2 is less than  sign-extended 16-bit immediate using unsigned comparison, then set $t1 to 1 else set $t1 to 0"),
    SLTU("sltu",    /**/ "000000ssssstttttfffff00000101011", false, "[sltu $t1,$t2,$t3]      Set less than unsigned : If $t2 is less than $t3 using unsigned comparision, then set $t1 to 1 else set $t1 to 0"),
    //乘除运算
    DIV("div",      /**/ "000000fffffsssss0000000000011010", false, "[div $t1,$t2]           Division with overflow : Divide $t1 by $t2 then set LO to quotient and HI to remainder (use mfhi to access HI, mflo to access LO)"),
    DIVU("divu",    /**/ "000000fffffsssss0000000000011011", false, "[divu $t1,$t2]          Division unsigned without overflow : Divide unsigned $t1 by $t2 then set LO to quotient and HI to remainder (use mfhi to access HI, mflo to access LO)"),
    MADD("madd",    /**/ "011100fffffsssss0000000000000000", false, "[madd $t1,$t2]          Multiply add : Multiply $t1 by $t2 then increment HI by high-order 32 bits of product, increment LO by low-order 32 bits of product (use mfhi to access HI, mflo to access LO)"),
    MADDU("maddu",  /**/ "011100fffffsssss0000000000000001", false, "[maddu $t1,$t2]         Multiply add unsigned : Multiply $t1 by $t2 then increment HI by high-order 32 bits of product, increment LO by low-order 32 bits of product, unsigned (use mfhi to access HI, mflo to access LO)"),
    MSUB("msub",    /**/ "011100fffffsssss0000000000000100", false, "[msub $t1,$t2]          Multiply subtract : Multiply $t1 by $t2 then decrement HI by high-order 32 bits of product, decrement LO by low-order 32 bits of product (use mfhi to access HI, mflo to access LO)"),
    MSUBU("msubu",  /**/ "011100fffffsssss0000000000000101", false, "[msubu $t1,$t2]         Multiply subtract unsigned : Multiply $t1 by $t2 then decrement HI by high-order 32 bits of product, decement LO by low-order 32 bits of product, unsigned (use mfhi to access HI, mflo to access LO)"),
    MUL("mul",      /**/ "011100ssssstttttfffff00000000010", false, "[mul $t1,$t2,$t3]       Multiplication without overflow  : Set HI to high-order 32 bits, LO and $t1 to low-order 32 bits of the product of $t2 and $t3 (use mfhi to access HI, mflo to access LO)"),
    MULT("mult",    /**/ "000000fffffsssss0000000000011000", false, "[mult $t1,$t2]          Multiplication : Set hi to high-order 32 bits, lo to low-order 32 bits of the product of $t1 and $t2 (use mfhi to access hi, mflo to access lo)"),
    MULTU("multu",  /**/ "000000fffffsssss0000000000011001", false, "[multu $t1,$t2]         Multiplication unsigned : Set HI to high-order 32 bits, LO to low-order 32 bits of the product of unsigned $t1 and $t2 (use mfhi to access HI, mflo to access LO)"),
    //累加器存取
    MFHI("mfhi",    /**/ "0000000000000000fffff00000010000", false, "[mfhi $t1]              Move from HI register : Set $t1 to contents of HI (see multiply and divide operations)"),
    MFLO("mflo",    /**/ "0000000000000000fffff00000010010", false, "[mflo $t1]              Move from LO register : Set $t1 to contents of LO (see multiply and divide operations)"),
    MTHI("mthi",    /**/ "000000fffff000000000000000010001", false, "[mthi $t1]              Move to HI registerr : Set HI to contents of $t1 (see multiply and divide operations)"),
    MTLO("mtlo",    /**/ "000000fffff000000000000000010011", false, "[mtlo $t1]              Move to LO register : Set LO to contents of $t1 (see multiply and divide operations)"),
    //分支跳转
    BEQ("beq",      /**/ "000100fffffssssstttttttttttttttt", false, "[beq $t1,$t2,label]    Branch if equal : Branch to statement at label's address if $t1 and $t2 are equal"),
    BGEZ("bgez",    /**/ "000001fffff00001ssssssssssssssss", false, "[bgez $t1,label]       Branch if greater than or equal to zero : Branch to statement at label's address if $t1 is greater than or equal to zero"),
    BGEZAL("bgezal",/**/ "000001fffff10001ssssssssssssssss", false, "[bgezal $t1,label]     Branch if greater then or equal to zero and link : If $t1 is greater than or equal to zero, then set $ra to the Program Counter and branch to statement at label's address"),
    BGTZ("bgtz",    /**/ "000111fffff00000ssssssssssssssss", false, "[bgtz $t1,label]       Branch if greater than zero : Branch to statement at label's address if $t1 is greater than zero"),
    BLEZ("blez",    /**/ "000110fffff00000ssssssssssssssss", false, "[blez $t1,label]       Branch if less than or equal to zero : Branch to statement at label's address if $t1 is less than or equal to zero"),
    BLTZ("bltz",    /**/ "000001fffff00000ssssssssssssssss", false, "[bltz $t1,label]       Branch if less than zero : Branch to statement at label's address if $t1 is less than zero"),
    BLTZAL("bltzal",/**/ "000001fffff10000ssssssssssssssss", false, "[bltzal $t1,label]     Branch if less than zero and link : If $t1 is less than or equal to zero, then set $ra to the Program Counter and branch to statement at label's address"),
    BNE("bne",      /**/ "000101fffffssssstttttttttttttttt", false, "[bne $t1,$t2,label]    Branch if not equal : Branch to statement at label's address if $t1 and $t2 are not equal"),
    J("j",          /**/ "000010ffffffffffffffffffffffffff", false, "[j target]             Jump unconditionally : Jump to statement at target address"),
    JAL("jal",      /**/ "000011ffffffffffffffffffffffffff", false, "[jal target]           Jump and link : Set $ra to Program Counter (return address) then jump to statement at target address"),
    JALR("jalr",    /**/ "000000sssss00000fffff00000001001", false, "[jalr $t1,$t2]         Jump and link register : Set $t1 to Program Counter (return address) then jump to statement whose address is in $t2"),
    JR("jr",        /**/ "000000fffff000000000000000001000", false, "[jr $t1]               Jump register unconditionally : Jump to statement whose address is in $t1"),
    //加载保存
    LB("lb",        /**/ "100000tttttfffffssssssssssssssss", false, "[lb $t1,-100($t2)]     Load byte : Set $t1 to sign-extended 8-bit value from effective memory byte address"),
    LBU("lbu",      /**/ "100100tttttfffffssssssssssssssss", false, "[lbu $t1,-100($t2)]    Load byte unsigned : Set $t1 to zero-extended 8-bit value from effective memory byte address"),
    LH("lh",        /**/ "100001tttttfffffssssssssssssssss", false, "[lh $t1,-100($t2)]     Load halfword : Set $t1 to sign-extended 16-bit value from effective memory halfword address"),
    LHU("lhu",      /**/ "100101tttttfffffssssssssssssssss", false, "[lhu $t1,-100($t2)]    Load halfword unsigned : Set $t1 to zero-extended 16-bit value from effective memory halfword address"),
    LW("lw",        /**/ "100011tttttfffffssssssssssssssss", false, "[lw $t1,-100($t2)]     Load word : Set $t1 to contents of effective memory word address"),
    LWL("lwl",      /**/ "100010tttttfffffssssssssssssssss", false, "[lwl $t1,-100($t2)]    Load word left : Load from 1 to 4 bytes left-justified into $t1, starting with effective memory byte address and continuing through the low-order byte of its word"),
    LWR("lwr",      /**/ "100110tttttfffffssssssssssssssss", false, "[lwr $t1,-100($t2)]    Load word right : Load from 1 to 4 bytes right-justified into $t1, starting with effective memory byte address and continuing through the high-order byte of its word"),
    SB("sb",        /**/ "101000tttttfffffssssssssssssssss", false, "[sb $t1,-100($t2)]     Store byte : Store the low-order 8 bits of $t1 into the effective memory byte address"),
    SH("sh",        /**/ "101001tttttfffffssssssssssssssss", false, "[sh $t1,-100($t2)]     Store halfword : Store the low-order 16 bits of $t1 into the effective memory halfword address"),
    SW("sw",        /**/ "101011tttttfffffssssssssssssssss", false, "[sw $t1,-100($t2)]     Store word : Store contents of $t1 into effective memory word address"),
    SWL("swl",      /**/ "101010tttttfffffssssssssssssssss", false, "[swl $t1,-100($t2)]    Store word left : Store high-order 1 to 4 bytes of $t1 into memory, starting with effective byte address and continuing through the low-order byte of its word"),
    SWR("swr",      /**/ "101110tttttfffffssssssssssssssss", false, "[swr $t1,-100($t2)]    Store word right : Store low-order 1 to 4 bytes of $t1 into memory, starting with high-order byte of word containing effective byte address and continuing through that byte address"),
    //读-修改-写
    LL("ll",        /**/ "110000tttttfffffssssssssssssssss", false, "[ll $t1,-100($t2)]     Load linked : Paired with Store Conditional (sc) to perform atomic read-modify-write.  Treated as equivalent to Load Word (lw) because MARS does not simulate multiple processors."),
    SC("sc",        /**/ "111000tttttfffffssssssssssssssss", false, "[sc $t1,-100($t2)]     Store conditional : Paired with Load Linked (ll) to perform atomic read-modify-write.  Stores $t1 value into effective address, then sets $t1 to 1 for success.  Always succeeds because MARS does not simulate multiple processors."),
    //协处理器0
    MFC0("mfc0",    /**/ "01000000000fffffsssss00000000000", false, "[mfc0 $t1,$8]          Move from Coprocessor 0 : Set $t1 to the value stored in Coprocessor 0 register $8"),
    MTC0("mtc0",    /**/ "01000000100fffffsssss00000000000", false, "[mtc0 $t1,$8]          Move to Coprocessor 0 : Set Coprocessor 0 register $8 to value stored in $t1"),
    ERET("eret",    /**/ "01000010000000000000000000011000", false, "[eret]                 Exception return : Set Program Counter to Coprocessor 0 EPC register value, set Coprocessor Status register bit 1 (exception level) to zero"),
    //协处理器1
    MOVF("movf",    /**/ "000000sssss00000fffff00000000001", false, "[movf $t1,$t2]         Move if FP condition flag 0 false : Set $t1 to $t2 if FPU (Coprocessor 1) condition flag 0 is false (zero)"),
    MOVT("movt",    /**/ "000000sssss00001fffff00000000001", false, "[movt $t1,$t2]         Move if FP condition flag 0 true : Set $t1 to $t2 if FPU (Coprocessor 1) condition flag 0 is true (one)"),

    /* 伪指令 */
    //算术运算
    LA("la", "", true, ""),
    LI("li", "", true, ""),
    MOVE("move", "", true, ""),
    NEGU("negu", "", true, ""),
    //逻辑运算
    NOT("not", "", true, ""),
    //分支跳转
    B("b", "", true, ""),
    BAL("bal", "", true, ""),
    BEQZ("beqz", "", true, ""),
    BNEZ("bnez", "", true, "");

    private String mnemonic;
    private String mask;
    private boolean isPseudo;
    private String description;

    OperationEnum(String mnemonic, String mask, boolean isPseudo, String description) {
        this.mnemonic = mnemonic;
        this.mask = mask;
        this.isPseudo = isPseudo;
        this.description = description;
    }

    public String getMnemonic() {
        return mnemonic;
    }

    public void setMnemonic(String mnemonic) {
        this.mnemonic = mnemonic;
    }

    public String getMask() {
        return mask;
    }

    public void setMask(String mask) {
        this.mask = mask;
    }

    public boolean isPseudo() {
        return isPseudo;
    }

    public void setPseudo(boolean pseudo) {
        isPseudo = pseudo;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
